package com.jilian.powerstation.http;

import android.os.SystemClock;
import android.util.Log;

import com.jilian.powerstation.common.event.MessageEvent;
import com.jilian.powerstation.utils.DataUtils;
import com.jilian.powerstation.utils.rxjava.RxBusBean;

import org.greenrobot.eventbus.EventBus;
import org.jetbrains.annotations.NotNull;

import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.net.Socket;
import java.util.Arrays;

public class SocketUtils {
    private static final String TAG = "SocketUtils";
    private static Thread receiveThread = null;
    private static boolean flag = false;
    private static Socket socket;
    private static InputStream inputStream = null;
    private static OutputStream outputStream = null;
    /**
     * 最近写或读时间
     */
    private static long LastTick = 0;

    public static void connectSocket() {
        Log.e(TAG, "connectSocket: 开始连接---------------------------------" );
        new Thread() {
            @Override
            public void run() {
                newTheadSend();
            }
        }.start();
    }


    /**
     * 连接Socket，因为是长连接，所以不能关闭该Socket，单独写一个方法来关闭socket以及输入流和输出流
     */
    private static void newTheadSend() {
        try {
            //创建Socket对象
            socket = new Socket("10.10.100.254", 8899);

//            socket = new Socket("10.10.100.254", 4530);
            flag = true;
            if (inputStream == null)
                inputStream = socket.getInputStream();//获取一个输入流，接收服务端的信息
            if (outputStream == null) {
                outputStream = socket.getOutputStream();
            }
            if (receiveThread == null) {
                /**
                 * 创建子线程接收串口数据
                 */
                receiveThread = new Thread() {
                    @Override
                    public void run() {
                        int receiveLength = 0;
                        while (flag) {
                            try {
                                if (inputStream == null)
                                {
                                    return;
                                }
                                int size = inputStream.available();
                                if (size > 0 && size == receiveLength)
                                {
                                    byte[] readData;
                                    //暂存每次返回数据长度，不变的时候为读取完数据
                                    readData = new byte[size];
                                    size = inputStream.read(readData);
                                    String hexString = DataUtils.ByteArrToHex(readData);
                                    String[] hexArray = hexString.split(" ");
                                    Log.e(TAG, "接受到的最原始的数据:" + hexString);
                                    String stringBuffer = getStringBuilder(hexArray);
                                    //数据长度是反向获取因此下标23和下标22更换顺序拼接并转换为int即可
                                    int contentLength = DataUtils.HexToInt(hexArray[23] + hexArray[22]);
                                    Log.e(TAG, "设备识别码:" + stringBuffer);
                                    Log.e(TAG, "数据来源:" + hexArray[21]);
                                    Log.e(TAG, "数据单元长度:" + hexArray[22] + " " + hexArray[23]);
                                    Log.e(TAG, "数据单元长度(16进制转换回10进制):" + contentLength);
                                    Log.e(TAG, "通过校验和的算法验证校验数据(16进制):" + getBCC(readData));
                                    Log.e(TAG, "数据总长度:" + hexArray.length);
                                    if (hexArray[hexArray.length - 1].equals(getBCC(readData))) {
                                        Log.e(TAG, "------------当前数据校验通过------------- " );
                                        String[] strings = new String[contentLength];
                                        //System.arraycopy(源数组名称，源数组开始点，目标数组名称，目标数组开始点，拷贝长度);
                                        System.arraycopy(hexArray, 24, strings, 0, contentLength);
                                        Log.e(TAG, "接受到的从年月日开始的数据:" + Arrays.toString(strings));
                                        //RxBus.getInstanceBus().post(new RxBusBean.SendMessage(strings, readData));

                                        MessageEvent messageEvent = new MessageEvent();
                                        messageEvent.setSendMessage(new RxBusBean.SendMessage(strings, readData));
                                        EventBus.getDefault().post(messageEvent);
                                    }
                                    else{
                                        Log.e(TAG, "-------------当前数据校验不通过------------- " );
                                    }
                                }
                                else {
                                    receiveLength = size;
                                }
                                SystemClock.sleep(10);
                            } catch (Exception e) {
                                e.printStackTrace();
                            }
                        }
                    }

                };
                //启动接收线程
                receiveThread.start();
            }
        }catch (Exception e) {
            Log.e(TAG, "newTheadSend: "+e.getLocalizedMessage());
            e.printStackTrace();
            flag = false;
        }
    }

    /**
     * 获取设备标识
     *
     * @param hexArray
     * @return
     */
    @NotNull
    public static String getStringBuilder(String[] hexArray) {
        StringBuilder stringBuffer = new StringBuilder();
        for (int i = 0; i < 17; i++) {
            if (i == 16) {
                stringBuffer.append(hexArray[4 + i]);
            } else
                stringBuffer.append(hexArray[4 + i]).append(",");
        }
        return stringBuffer.toString();
    }

    /**
     * 发送串口数据的方法
     */
    public static void sendSerialPort(byte[] sendData) {
        try {
            Log.e("SocketUtils", "发送的16进制指令: " + DataUtils.hexBytesToString(sendData));
            if (socket != null && outputStream != null && inputStream != null) {
                long tick = LastTick + 200 - System.currentTimeMillis();
                if (tick > 0) {
                    SystemClock.sleep(tick);
                }
                if (outputStream != null && sendData != null) {
                    outputStream.write(sendData);
                    outputStream.flush();
                    LastTick = System.currentTimeMillis();
                    StringBuilder

                            stringBuffer = new StringBuilder("[");
                    for (int i = 0; i < DataUtils.hexBytesToString(sendData).length(); i += 2) {
                        stringBuffer.append(DataUtils.hexBytesToString(sendData).substring(i, i + 2)).append(",");
                    }
                    stringBuffer.replace(stringBuffer.length() - 1, stringBuffer.length(), "]");
                    Log.e("SocketUtils", "发送的16进制指令: " + stringBuffer.toString());
                    Log.e("SocketUtils", "串口数据发送成功");
                }
            }
        } catch (Exception e) {
            LastTick = System.currentTimeMillis();
            e.printStackTrace();
            Log.e("SocketUtils", "串口数据发送失败"+e.getMessage());
            closeSocket();
        }
    }

    public static void closeSocket() {
        try {
            if (receiveThread != null) {
                receiveThread.interrupt();
                receiveThread = null;
            }
            if (outputStream != null) {
                outputStream.flush();
                outputStream.close();
                outputStream = null;
            }
            if (inputStream != null) {
                inputStream.close();
                inputStream = null;
            }
            if (socket != null) {
                if (socket.isConnected()) {
                    socket.close();
                    flag = false;
                }
                socket = null;
            }
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 校验和算法，根据文档看，从命令单元[数据第3位]到倒数第二组数据按位运算得到的数据转换为十六位
     *
     * @param data 接收到的数据
     * @return 返回的是按位运算的结果，BBC算法结果，16进制；
     */
    public static String getBCC(byte[] data) {

        String ret = "";
        byte[] BCC = new byte[1];
        for (int i = 2; i < data.length - 1; i++) {
            BCC[0] = (byte) (BCC[0] ^ data[i]);
        }
        String hex = Integer.toHexString(BCC[0] & 0xFF);
        if (hex.length() == 1) {
            hex = '0' + hex;
        }
        ret += hex.toUpperCase();
        return ret;
    }

    public static String byteArrayToHexString(byte[] b) {
        StringBuilder resultSb = new StringBuilder();
        for (int i = 0; i < b.length; i++) {
            resultSb.append(byteToHexString(b[i]));
        }
        return resultSb.toString();
    }

    private static String byteToHexString(byte b) {
        int n = b;
        if (n < 0)
            n = 256 + n;
        int d1 = n / 16;
        int d2 = n % 16;
        return hexDigits[d1] + hexDigits[d2];
    }

    private final static String[] hexDigits = {"0", "1", "2", "3", "4", "5",
            "6", "7", "8", "9", "A", "B", "C", "D", "E", "F"};



}
